package com.xingdata.jjxc.http;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.params.ConnManagerParams;
import org.apache.http.conn.params.ConnPerRouteBean;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.util.EntityUtils;

import android.app.Activity;
import android.content.Context;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import com.alibaba.fastjson.JSON;
import com.xingdata.jjxc.enty.RespEntity;
import com.xingdata.jjxc.utils.ThreadPoolManager;
import com.xingdata.jjxc.utils.callback.FileSizeCallBack;

/**
 * 网络连接工具类
 * 
 * 项目名称：JJXC_VPN 类名称：HttpUtil 类描述： 创建人：JiangMin 创建时间：2015-6-3 下午1:42:26 修改备注：
 * 
 * @version
 * 
 */
public class HttpUtil extends Thread {
	private static String TAG = "HttpUtil";
	public static final int SO_TIMEOUT = 20 * 1000;
	public static final int CONNECTION_TIMEOUT = 20 * 1000;
	private HttpResponse httpResponse = null;// 返回的响应
	private HttpEntity httpEntity = null;// 相应实体
	private static HttpUtil httpUtil;
	private Context context = null;
	private int timeout = 10000;
	@SuppressWarnings("rawtypes")
	private List lparams = new LinkedList();
	public static Object objectDownload = new Object();
	private MultipartEntity multipartEntity;
	private RespEntity respEntity;
	public static final int UPDATE = 0;// 更新
	public static final int SUCCESS = 1;// 成功
	public static final int FAIL = 2;// 失败
	public static final int SIZE = 3;// 长度
	public static boolean isCancel=false;// 取消
	private static HttpResponseListener httpResponseListener;
	private static FileSizeCallBack fileSizeCallBack;
	private Bundle mBundle;
	private Message message;
	private Object synDownload=new Object();

	private HttpUtil(Context context) {
		this.context = context;
	}

	public static HttpUtil getInstance(Context context) {
		if (httpUtil == null) {
			httpUtil = new HttpUtil(context);
		}
		return httpUtil;
	}

	/**
	 * 向服务端发送请求
	 * 
	 * @param map
	 *            参数MAP
	 * @param path
	 *            接口URL
	 * @param httpResponseListener
	 *            回调监听
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public void Post(String path, HashMap<String, String> map,
			HttpResponseListener httpResponseListener) {
		post(path, map, SO_TIMEOUT * 30, httpResponseListener);
	}

	/**
	 * 向服务端发送请求
	 * 
	 * @param map
	 *            参数MAP
	 * @param path
	 *            接口URL
	 * @param httpResponseListener
	 *            回调监听
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public void PostFile(String path, HashMap<String, Object> map,
			HttpResponseListener httpResponseListener) {
		postFile(path, map, SO_TIMEOUT * 30, httpResponseListener);
	}

	private void postFile(final String path, HashMap<String, Object> map,
			int waitTime, final HttpResponseListener listener) {
		httpResponseListener = listener;
		multipartEntity = new MultipartEntity();
		if (lparams != null) {
			lparams.clear();
		}
		for (Map.Entry<String, Object> entry : map.entrySet()) {
			if (entry.getValue() instanceof String) {
				// lparams.add(new BasicNameValuePair(entry.getKey(), entry
				// .getValue().toString()));
				try {
					multipartEntity.addPart(entry.getKey(), new StringBody(
							entry.getValue().toString()));
				} catch (UnsupportedEncodingException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			} else if (entry.getValue() instanceof File) {
				FileBody fileBody = new FileBody((File) entry.getValue());
				multipartEntity.addPart("file", fileBody);
			}
		}
		ThreadPoolManager.getInstance().addTask(new Runnable() {
			@Override
			public void run() {
				try {
					synchronized (objectDownload) {
						message = new Message();
						Log.i("BaseUrl", "path -->" + path.toString());
						HttpPost httpPost = new HttpPost(path);
						httpPost.setEntity(multipartEntity);
						BasicHttpParams httpParams = new BasicHttpParams();
						ConnManagerParams.setTimeout(httpParams, timeout);
						ConnManagerParams.setMaxConnectionsPerRoute(httpParams,
								new ConnPerRouteBean(10));
						ConnManagerParams
								.setMaxTotalConnections(httpParams, 10);
						HttpConnectionParams.setSoTimeout(httpParams, timeout);
						HttpConnectionParams.setConnectionTimeout(httpParams,
								timeout);
						HttpConnectionParams.setTcpNoDelay(httpParams, true);
						HttpConnectionParams.setSocketBufferSize(httpParams,
								8192);
						HttpProtocolParams.setVersion(httpParams,
								HttpVersion.HTTP_1_1);
						HttpProtocolParams.setUserAgent(
								httpParams,
								String.format(
										"andbase-http/%s (http://www.418log.org/)",
										new Object[] { Double.valueOf(1.0D) }));
						httpPost.setParams(httpParams);
						HttpClient httpClient = new DefaultHttpClient();
						httpResponse = httpClient.execute(httpPost);
						if (httpResponse.getStatusLine().getStatusCode() == 200) {
							// 得到返回的实体
							httpEntity = httpResponse.getEntity();
							InputStream inputStream = httpEntity.getContent();
							BufferedReader reader = new BufferedReader(
									new InputStreamReader(inputStream));
							StringBuffer resultBuffer = new StringBuffer();
							String line = "";
							try {
								while ((line = reader.readLine()) != null) {
									resultBuffer.append(line);
								}
								respEntity = JSON.parseObject(
										resultBuffer.toString(),
										RespEntity.class);
								Log.i(TAG, respEntity.getMsg());
								if (respEntity.getState() == 0) {
									// httpResponseListener.onSuccess(JSON
									// .parseObject(
									// resultBuffer.toString(),
									// RespEntity.class));
									mBundle = new Bundle();
									mBundle.putSerializable("entity", JSON
											.parseObject(
													resultBuffer.toString(),
													RespEntity.class));

									message.what = SUCCESS;
									message.setData(mBundle);
									handler.sendMessage(message);
								} else {
									message.what = FAIL;
									message.obj = respEntity.getMsg();
									handler.sendMessage(message);
									// httpResponseListener.onFailure(respEntity
									// .getMsg());
								}

								// httpResponseListener.onSuccess(resultBuffer
								// .toString());
								// respEntity=JSON.parseObject(resultBuffer
								// .toString(), RespEntity.class);
							} catch (IOException e) {
								message.what = FAIL;
								message.obj = "服务器异常";
								handler.sendMessage(message);
							} finally {
								if (inputStream != null) {
									inputStream.close();
								}
							}
						} else {
							Log.i("BaseUrl", "path -->"
									+ CommonConstant.CONNECTION_REFUSED);
							message.what = FAIL;
							message.obj = "服务器异常";
							handler.sendMessage(message);
							// httpResponseListener
							// .onFailure(CommonConstant.CONNECTION_REFUSED);
						}
						return;

					}
				} catch (IOException exception) {
					message.what = FAIL;
					message.obj = "服务器异常";
					handler.sendMessage(message);
				}
			}
		});

	}

	@SuppressWarnings("unchecked")
	private void post(final String path, final HashMap<String, String> map,
			final int waitTime, final HttpResponseListener listener) {

		ThreadPoolManager.getInstance().addTask(new Runnable() {
			@Override
			public void run() {
				try {
					synchronized (objectDownload) {
						httpResponseListener = listener;
						message = new Message();
						if (!isNetWork()) {
							message.what = FAIL;
							message.obj = "当前网络不稳定";
							handler.sendMessage(message);
							return;
						}
						;

			
						if (lparams != null) {
							lparams.clear();
						}
						for (Map.Entry<String, String> entry : map.entrySet()) {
							lparams.add(new BasicNameValuePair(entry.getKey(),
									entry.getValue()));
						}
						Log.i("BaseUrl", "path -->" + path.toString());
						HttpPost httpPost = new HttpPost(path);
						httpPost.setEntity(new UrlEncodedFormEntity(lparams,
								"UTF-8"));
						BasicHttpParams httpParams = new BasicHttpParams();
						ConnManagerParams.setTimeout(httpParams, timeout);
						ConnManagerParams.setMaxConnectionsPerRoute(httpParams,
								new ConnPerRouteBean(10));
						ConnManagerParams
								.setMaxTotalConnections(httpParams, 10);
						HttpConnectionParams.setSoTimeout(httpParams, timeout);
						HttpConnectionParams.setConnectionTimeout(httpParams,
								timeout);
						HttpConnectionParams.setTcpNoDelay(httpParams, true);
						HttpConnectionParams.setSocketBufferSize(httpParams,
								8192);
						HttpProtocolParams.setVersion(httpParams,
								HttpVersion.HTTP_1_1);
						HttpProtocolParams.setUserAgent(
								httpParams,
								String.format(
										"andbase-http/%s (http://www.418log.org/)",
										new Object[] { Double.valueOf(1.0D) }));
						httpPost.setParams(httpParams);
						HttpClient httpClient = new DefaultHttpClient();
						httpResponse = httpClient.execute(httpPost);
						if (httpResponse.getStatusLine().getStatusCode() == 200) {
							// 得到返回的实体
							httpEntity = httpResponse.getEntity();
							InputStream inputStream = httpEntity.getContent();
							BufferedReader reader = new BufferedReader(
									new InputStreamReader(inputStream));
							StringBuffer resultBuffer = new StringBuffer();
							String line = "";
							try {
								while ((line = reader.readLine()) != null) {
									resultBuffer.append(line);
								}

								respEntity = JSON.parseObject(
										resultBuffer.toString(),
										RespEntity.class);
								if (respEntity.getMsg() != null) {
									Log.i(TAG, respEntity.getMsg());
								} else {
									Log.i(TAG, "msg is null");
								}
								
								if (respEntity.getResult()==null) {
									message.what = FAIL;
									message.obj = respEntity.getMsg();
									handler.sendMessage(message);
									return;
								}else if (respEntity.getResult().equals("{}")) {
									respEntity.setResult("[]");
								}
								if (respEntity.getState() == 0) {
									mBundle = new Bundle();
									mBundle.putSerializable("entity", respEntity);

									message.what = SUCCESS;
									message.setData(mBundle);
									handler.sendMessage(message);
									// httpResponseListener.onSuccess(JSON
									// .parseObject(
									// resultBuffer.toString(),
									// RespEntity.class));
								} else {
									// httpResponseListener.onFailure(respEntity
									// .getMsg());
									message.what = FAIL;
									message.obj = respEntity.getMsg();
									handler.sendMessage(message);
								}
							} catch (IOException e) {
								e.printStackTrace();
							} finally {
								if (inputStream != null) {
									inputStream.close();
								}
							}
						} else {
							// Log.i("BaseUrl", "path -->"
							// + CommonConstant.CONNECTION_REFUSED);
							// httpResponseListener
							// .onFailure(CommonConstant.CONNECTION_REFUSED);
							message.what = FAIL;
							message.obj = "服务器异常";
							handler.sendMessage(message);
						}
					}
				} catch (IOException exception) {
					message.what = FAIL;
					message.obj = "服务器异常";
					handler.sendMessage(message);
				}
			}

			
		});
	}

	
	private boolean isNetWork() {
		
		ConnectivityManager cwjManager = (ConnectivityManager) ((Activity) context)
				.getSystemService(Context.CONNECTIVITY_SERVICE);
		cwjManager.getActiveNetworkInfo();
		return cwjManager.getActiveNetworkInfo() != null;
	}
	/**
	 * HttpGet方式请求
	 * 
	 * @param path
	 */
	public void requestByHttpGet(final String path,
			HttpResponseListener listener) {
		Log.i(TAG, path);
		httpResponseListener = listener;

		ThreadPoolManager.getInstance().addTask(new Runnable() {
			@Override
			public void run() {
				try {
					String result = "";
					path.replaceAll(" ", "");
					// 新建HttpGet对象
					HttpGet httpGet = new HttpGet(path);
					// 获取HttpClient对象
					HttpClient httpClient = new DefaultHttpClient();
					// 获取HttpResponse实例
					HttpResponse httpResp;
					httpResp = httpClient.execute(httpGet);
					// 判断是够请求成功
					if (httpResp.getStatusLine().getStatusCode() == 200) {
						// 获取返回的数据
						result = EntityUtils.toString(httpResp.getEntity(),
								"UTF-8");
						// 因为返回的数据为不规则数据这里需要手动组装数据
						RespEntity entity = new RespEntity();
						entity.setState(0);
						entity.setMsg(result);
						mBundle = new Bundle();
						mBundle.putSerializable("entity", entity);
						message = new Message();
						message.what = SUCCESS;
						message.setData(mBundle);
						handler.sendMessage(message);
						Log.i(TAG, "HttpGet方式请求成功，返回数据如下：");
						Log.i(TAG, result);
					} else {
						message = new Message();
						message.what = FAIL;
						Log.i(TAG, "HttpGet方式请求失败");
						message.obj = "请求失败";
						handler.sendMessage(message);
					}
				} catch (ClientProtocolException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					message = new Message();
					message.what = FAIL;
					message.obj = "请求失败";
					handler.sendMessage(message);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					message = new Message();
					message.what = FAIL;
					message.obj = "请求失败";
					handler.sendMessage(message);
				}
			}
		});

	}

	/**
	 * 下载文件
	 * @param strUrl 下载地址
	 * @param localUrl 存储地址
	 * @param listener 回调
	 */
	public void downloadFile(final String strUrl, final String localUrl,
			HttpResponseListener listener) {
		httpResponseListener = listener;
		isCancel=false;
		new Thread() {
			@Override
			public void run() {
				super.run();
				synchronized (synDownload) {
					HttpURLConnection c = null;
					try {
						String progress="";
						URL url = new URL(strUrl);
						c = (HttpURLConnection) url.openConnection();
						c.setRequestMethod("GET");
						c.setConnectTimeout(timeout);
						c.setDoOutput(true);
						c.connect();
						if (c.getResponseCode() == 200) {
							// 计算文件长度
							int lenghtOfFile = c.getContentLength();
							FileOutputStream f = new FileOutputStream(new File(
									localUrl));
							InputStream in = c.getInputStream();
							// 下载的代码
							byte[] buffer = new byte[1024];
							int len1 = 0;
							long total = 0;
							while (!isCancel) {
								message = new Message();
								len1 = in.read(buffer);
								total += len1; // total = total + len1
								
								int inProgress=(int) ((total * 100) / lenghtOfFile);
								if (!progress.equals(inProgress+"")) {
									progress = ""
											+ (int) ((total * 100) / lenghtOfFile);
									message.what = UPDATE;
									message.obj = progress;
									handler.sendMessage(message);
								}
								if (len1 <= 0) {
									message.what = UPDATE;
									message.obj = "100";
									handler.sendEmptyMessage(SUCCESS);
									break;
								}
								f.write(buffer, 0, len1);

							}
							//手动取消
							if (isCancel) {
								c.disconnect();
								Log.i(TAG, "手动取消...");
							}
							f.close();
							in.close();
						} else {
							message = new Message();
							message.what = FAIL;
							message.obj = "请求失败";
							handler.sendMessage(message);
						}
						if (c != null) {
							c.disconnect();
						}

					} catch (Exception e) {
						message = new Message();
						message.what = FAIL;
						message.obj = "请求失败";
						handler.sendMessage(message);
					}

				
				}
}
		}.start();
	}

	private Handler handler = new Handler() {
		public void handleMessage(android.os.Message msg) {
			switch (msg.what) {
			case UPDATE:
				if (httpResponseListener != null) {
					httpResponseListener.onLoading(Integer.parseInt(msg.obj
							.toString()));
					Log.i(TAG, "文件下载   " + Integer.parseInt(msg.obj.toString())
							+ "%");
				}
				break;
			case SUCCESS:
				if (httpResponseListener != null) {
					httpResponseListener.onSuccess((RespEntity) msg.getData()
							.getSerializable("entity"));
				}
				break;
			case FAIL:
				if (httpResponseListener != null) {
					httpResponseListener.onFailure(msg.obj.toString());
				}
				break;

			case SIZE:
				if (fileSizeCallBack != null) {
					fileSizeCallBack.onFileSize(msg.getData().getString("size"));
				}
				break;
			}
		};
	};

	/**
	 * 获取网络文件大小
	 * 
	 * @param fileSizeCallBack
	 * 
	 * @param url
	 * @return
	 */
	public void getFileSize(final FileSizeCallBack callback, final String strUrl) {
		fileSizeCallBack = callback;
		ThreadPoolManager.getInstance().addTask(new Thread(new Runnable() {
			@Override
			public void run() {
				URL url = null;
				try {
					url = new URL(strUrl);
					URLConnection uc = url.openConnection();
					float num = (float) uc.getContentLength() / 1024 / 1024;
					DecimalFormat df = new DecimalFormat("0.00");// 格式化小数
					mBundle = new Bundle();
					message = new Message();
					mBundle.putString("size", (df.format(num) + "M"));
					message.setData(mBundle);
					message.what = SIZE;
					handler.sendMessage(message);
				} catch (MalformedURLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (UnsupportedEncodingException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}));

	};
}
